<?php

/*
    This file is part of TFCMS.

    TFCMS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    TFCMS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with TFCMS. If not, see <http://www.gnu.org/licenses/>.
*/

/*!
 *	\class SiteMap
 *	\file sitemap.class.php
 *	\brief Sitemap XML generator class.
 *
 *	SiteMap is used mostly to render the navigational structure of TFCMSModel for search engines (specifically Google).
 */

class SiteMap {

	private $def_change_freq = "monthly";
	private $def_priority = 0.5;
	private $model;
	private $script_name = "index.php";

	/** \brief sitemap constructor
	 *
	 *	@param double $priority Range: 0.0 through 1.0
	 *	@param string $changefreq Possible values: always, hourly, daily, weekly, monthly, yearly, never
	 */
	function __construct($priority = NULL,
						 $changefreq = NULL,
						 $script_name = NULL)
		{
			if ($priority)
				$this->def_priority = $priority;

			if ($changefreq)
				$this->def_change_freq = $changefreq;

			if ($script_name)
				$this->script_name = $script_name;

			define("DOCROOT", preg_replace("`/$`", "", $_SERVER['DOCUMENT_ROOT']));
			define("SITEURL", "http://".$_SERVER['SERVER_NAME']."/");
		}

	function addDynamicPage($pagename = NULL,
							$categories = NULL,
							$keys = NULL,
							$lastmod = NULL,
							$priority = NULL,
							$changefreq = NULL)
		{
			/*
			 *	assuming URL: http://localhost/cat1/cat2/file_name?key1=value&key2=value
			 *
			 *	addDynamicPage
			 *		(
			 *			"file_name",
			 *			array("cat1", "cat2"),
			 *			array
			 *				(
			 *					"key1" => "value",
			 *					"key2" => "value"
			 *				)
			 *		)
			*/
			if (!$priority)
				$priority = $this->def_priority;

			if (!$changefreq)
				$changefreq = $this->def_change_freq;

			if (is_array($categories))
				$categories = implode("/", $categories);

			$this->dynamicPages[] = array
				(
					"loc" => (!is_null($categories)) ? htmlentities($categories."/".$pagename.$this->implodeKeysWithValues("=", $keys)) : htmlentities($pagename.$this->implodeKeysWithValues("=", $keys)),
					"lastmod" => $lastmod,
					"priority" => $priority,
					"changefreq" => $changefreq
				);
		}

	function addStaticPage($loc, $priority=NULL, $changefreq=NULL)
		{
			/* Forces "current working directy" to DOCUMENT_ROOT */
			$loc = preg_replace('`^\.\.?/`', "", $loc);

			if (!$priority)
				$priority = $this->def_priority;

			if (!$changefreq)
				$changefreq = $this->def_change_freq;

			if (file_exists(DOCROOT.$loc))
			{
				$this->staticPages[] = array
					(
						"loc" => htmlentities($loc),
						"lastmod" => date("Y-m-d",filemtime(DOCROOT.$loc)),
						"priority" => $priority,
						"changefreq" => $changefreq
					);
			}
		}

	function addDirectory($dir, $priority=NULL, $changefreq=NULL)
		{
			/*	Constructs an absolute-relative URL
			 *	 for each file in the directory.
			*/
			$dir = preg_replace('`^\.\.?/`', "", $dir);
			$dir = preg_replace('`/$`', "", $dir);
			foreach (scandir(DOCROOT.$dir) as $value)
			{
				if ($value != "." && $value != ".." && file_exists(DOCROOT.$dir."/".$value))
					$this->addStaticPage($dir."/".$value);
			}
		}

	protected function implodeKeysWithValues($glue, $keys)
		{
			if (!is_array($keys) && empty($keys))
				return;

			foreach ($keys as $key => $value)
			{
				if (isset($return))
					$return .= "&";

				$return .= $key.$glue.$keys[$key];
			}

			return "?".$return;
		}

	protected function genXmlData()
		{
			$body .= "\t<url>\n";
			$body .= "\t\t<loc>".SITEURL."</loc>\n";
			$body .= "\t\t<priority>0.9</priority>\n";
			$body .= "\t\t<changefreq>weekly</changefreq>\n";
			$body .= "\t</url>\n";

			if (is_array($this->dynamicPages))
			{
				foreach ($this->dynamicPages as $key => $value)
				{
					$body .= "\t<url>\n";
					$body .= "\t\t<loc>".SITEURL.$this->dynamicPages[$key]['loc']."</loc>\n";
					if (!empty($this->dynamicPages[$key]['lastmod'])){
						$body .= "\t\t<lastmod>".$this->dynamicPages[$key]['lastmod']."</lastmod>\n";
					}
					$body .= "\t\t<priority>".$this->dynamicPages[$key]['priority']."</priority>\n";
					$body .= "\t\t<changefreq>".$this->dynamicPages[$key]['changefreq']."</changefreq>\n";
					$body .= "\t</url>\n";
				}
			}

			if (is_array($this->staticPages))
			{
				foreach ($this->staticPages as $key => $value)
				{
					$body .= "\t<url>\n";
					$body .= "\t\t<loc>".SITEURL.preg_replace("#^/#", "", $this->staticPages[$key]['loc'])."</loc>\n";

					if (!empty($this->staticPages[$key]['lastmod']))
						$body .= "\t\t<lastmod>".$this->staticPages[$key]['lastmod']."</lastmod>\n";

					$body .= "\t\t<priority>".$this->staticPages[$key]['priority']."</priority>\n";
					$body .= "\t\t<changefreq>".$this->staticPages[$key]['changefreq']."</changefreq>\n";
					$body .= "\t</url>\n";
				}
			}

			return $body;
		}

	protected function getDataFromModel(&$model)
		{
			$model->updateDirCache();
			foreach ($model->getCategories() as $category)
			{
				$name = str_replace(" ", "_", strtolower($category['name']));
				$name = preg_replace("#[^\w\d]#", "", $name);
				if (!empty($category['file']))
					$this->addDynamicPage($name, array($this->script_name));

				else if (!empty($category['url'])
				 && !preg_match("#^http://#", $category['url']))
					$this->addStaticPage($category['url']);

				foreach ((array) $category['dirs'] as $dir)
				{
					foreach ($dir as $file)
					{
						$file_name = pathinfo($file);
						$file_name = $file_name['filename'];
						$file_name = preg_replace("#[^\w\d]#", "", $file_name);
						$this->addDynamicPage($file_name, array($this->script_name, $name));
					}
				}

				foreach ((array) $category['links'] as $link)
				{
					$link = split("=", $link);
					if (!preg_match("#^http://#", $link[1]))
						$this->addStaticPage($link[1]);
				}
			}
		}

	function renderXml()
		{
			header("Content-type: application/xml");
			echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			echo "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
			if ($this->model)
				$this->getDataFromModel($this->model);
			echo $this->genXmlData();
			echo "</urlset>\n";
		}

	function renderXml2File($path)
		{
			ob_start();
			$this->renderXml();
			$content = ob_get_contents();
			ob_end_clean();

			file_put_contents($path, $content);
		}

	function setModel(TFCMSAbstractModel &$model)
		{
			$this->model = $model;
		}
}

?>
